﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.IdentityModel.Web;
using System.Web;
using System.Web.SessionState;
using System.IdentityModel.Tokens;
using Microsoft.IdentityModel.Claims;
using Microsoft.IdentityModel.Protocols.WSFederation;
using System.Globalization;
using System.IO;

namespace Veracruz.Facebook.Sharepoint.Handlers
{
    public sealed class FacebookLoginHandler
        : IHttpHandler, IRequiresSessionState
    {

        [Obsolete("Cache token Session key const")]
        public const string CachedToken = "CachedToken";


        #region IHttpHandler Members

        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext context)
        {
            FederatedAuthenticationModule l_federatedAuthenticationModule = FederatedAuthenticationModule.Current;

            //HACK
            if (!context.Request.IsAuthenticated)
            {
                if (!l_federatedAuthenticationModule.IsPassiveSignInResponse(context.Request))
                {
                    // User is trying to get to the page w/o being authenticated
                    // We are going to redirect him to our STS. The address is stored in FAM.Issuer property
                    l_federatedAuthenticationModule.RedirectToIdentityProvider(context);
                }
                else
                {
                    //
                    // We have a WS-Federation Passive Protocol SignIn Response message from the STS. 
                    // Extract the token and attempt to sign-in the user
                    //

                    // Get the xml token from the form post
                    string l_tokenXml = l_federatedAuthenticationModule.GetXmlTokenFromPassiveSignInResponse(context.Request, null);

                    if (String.IsNullOrEmpty(l_tokenXml))
                    {
                        throw new InvalidOperationException("Cannot parse the returned security token");
                    }

                    // Validate the token
                    SecurityToken token = null;
                    IClaimsPrincipal l_principal = l_federatedAuthenticationModule.AuthenticateUser(l_tokenXml, out token);

                    // store the token in the session for later use
                    if (context.Session == null)
                    {
                        throw new Exception("No session available to save the token");
                    }
                    context.Session[CachedToken] = token;

                    // Perform Signin. 
                    string l_signOutUrl = GetPathAndQuery(new SignOutRequestMessage(new Uri(l_federatedAuthenticationModule.Issuer)));

                    // The second param in SignInParameters.ctor denotes whether a persistent cookie is issued or not. 
                    l_federatedAuthenticationModule.IssueTicket(new TicketGenerationContext(l_principal, false, l_signOutUrl, GetType().Name));


                    context.Response.Redirect("~/", true);
                }
            }
        }

        private static string GetPathAndQuery(WSFederationMessage request)
        {
            StringBuilder l_strb = new StringBuilder(128);
            using (StringWriter writer = new StringWriter(l_strb, CultureInfo.InvariantCulture))
            {
                request.Write(writer);
                return l_strb.ToString();
            }
        }

        #endregion
    }
}
